#pragma once
#include <iostream>
#include <string>

const std::string blank_space_sep = " ";
const std::string protocol_sep = "\n";
// 封装报头（添加报头）
std::string Encode(std::string &content)
{
    std::string package = std::to_string(content.size()); // 报头中第一个字段是表征正文长度的
    package += protocol_sep;                              // 表征长度的字段后面加协议分割符，方便识别出正文长度
    package += content;                                   // 加上正文
    package += protocol_sep;                              // 报文结尾也加上协议分隔符，方便区分下一份报文
    return package;
}
//"len"\n"x op y",将报头蕴含的信息识别出来，提取出正文
bool Decode(std::string &package, std::string *content) // 第一个参数时输入型参数，第二个参数时输出型参数
{
    std::size_t pos = package.find(protocol_sep); // 找到换行分割符
    if (pos == std::string::npos)
        return false;
    std::string len_str = package.substr(0, pos); // len_str的长度是保存的是"len"这个字符的长度
    std::size_t len = std::stoi(len_str);         // 把报头的一个字段信息转成整数，拿到了有效载荷的字符串长度
    // package(报文的长度)=len_str+content_str+2,这里的2是两个换行符数量
    // 所以需要利用len长度检查发来的报文是否完整
    std::size_t total_len = len_str.size() + len + 2;
    if (package.size() < total_len) // 说明报文中的正文部分少了数据
        return false;
    // 提取正文
    *content = package.substr(pos + 1, len); // 起始位置，终止位置
    // 移除报文 "len"\n"x op y"xxxxxx
    package.erase(0, total_len); // 移除报文后，才处理剩下的报文
    return true;
}

class Request
{
public:
    Request(int data1, int data2, char oper) : x(data1), y(data2), op(oper)
    {
    }
    Request()
    {
    }

public:
    bool Serialize(std::string *out)
    {
        // 构建有效载荷 struct=>string "x op y"
        std::string s = std::to_string(x);
        s += blank_space_sep;
        s += op;
        s += blank_space_sep;
        s += std::to_string(y);
        *out = s;
        return true;
    }
    // 反序列化
    bool Deserialize(const std::string &in) //"len"\n"x op y"
    {
        // std::cout << "如果进入了这里说明能成功进入Deseri函数" << std::endl;
        std::size_t left = in.find(blank_space_sep); // 找到空格
        if (left == std::string::npos)
            return false;
        // std::cout << "完成截取做操作数的位置" << std::endl;
        std::string part_x = in.substr(0, left); // 截取的范围是左闭右开，找到后left+1

        std::size_t right = in.rfind(blank_space_sep);
        if (right == std::string::npos)
            return false;
        // std::cout << "完成截取右操作数的位置" << std::endl;
        std::string part_y = in.substr(right + 1); // 只传一个参数的话，substr会从这个参数的位置向后截取，知道读取到\0

        if (left + 2 != right) // left和right此时都指向空格，left+1就是字符op(op算一个字符，加减乘除就是一个字符)，+2就是right
            return false;
        // std::cout << "完成检查的工作" << std::endl;
        op = in[left + 1]; // 获取到字符类型的加减乘除
        // std::cout << "op的符号是" << op << std::endl;
        x = std::stoi(part_x); // 转整型
        // std::cout << "x的值是" << x << std::endl;
        y = std::stoi(part_y);
        // std::cout << "y的值是" << y << std::endl;
        return true;
    }

    void DebugPrint()
    {
        std::cout << "新请求构建完成：" << x << op << y << "=?" << std::endl;
    }

public:
    //  x op y
    int x;
    int y;
    char op; //+ - * / %
};

class Response
{
public:
    Response(int res, int c) : result_(res), code_(c)
    {
    }
    Response()
    {
    }

public:
    // 序列化   输出型参数
    bool Serialize(std::string *out)
    {
        //"len"\n"result code"
        // 构建有效载荷
        std::string s = std::to_string(result_);
        s += blank_space_sep;
        s += std::to_string(code_);
        *out = s;
        return true;
    }
    bool Deserialize(const std::string &in) //"result code"
    {
        std::size_t pos = in.find(blank_space_sep); // 找到空格
        if (pos == std::string::npos)
            return false;
        std::string part_left = in.substr(0, pos++);
        std::string part_right = in.substr(pos + 1);
        result_ = std::stoi(part_left);
        code_ = std::stoi(part_right);
        return true;
    }
    void DebugPrint()
    {
        std::cout << "结果相应完成完成，result:" << result_ << ",code:" << code_ << std::endl;
    }

public:
    int result_;
    int code_; // 0表示可信，非0，具体是几，表明对应的错误原因
};